#include <dos.h>
#include <pc.h>
#include "queue.h"
#include "ints.h"
#include "timer.h"

int counter;


void queueInit(Queue *q) 
{
    q->in = q->out = q->cnt = 0;
    q->size = 10;
}



void teste() {
	//printf("teste called");
	//counter++;
}



Bool queuePut(Queue *q, char c) 
{
	//printf("queuePut called: q=%p , c=%c \n",q,c);
	
	counter++;
	
	void beep(void);
	
    if (queueFull(q)) {
	
		beep(); // warning, uses T0 ints!
		
        return false;
	}
    
    q->buf[q->in++] = c;
    q->in %= q->size;
    q->cnt++;
	
    //counter++;
	
    return true;
}

// called from C. As it can be interrupted by the isr and manipulates structure fields it is a critical section
int queueGet(Queue *q) 
{	
	disable_irq(KBD_IRQ); // critical section, disable kbd interrupts
	
    if (queueEmpty(q)) 
	{
		enable(); // reenable interrupts
		//enable_irq(KBD_IRQ);
        return -1;
	}
    
    char c = q->buf[q->out++];
	
    q->out %= q->size;
    q->cnt--;
	
	enable_irq(KBD_IRQ); // end of critical section, reenable interrupts
	
    return c;
}



// should be critical a section
Bool queueEmpty(Queue *q) 
{
    return q->cnt == 0;
}




// should be critical a section
Bool queueFull(Queue *q) 
{
    return q->cnt == q->size;
}




unsigned int milisec = 0;

void timer_0_handler(void) 
{
	disable_irq(KBD_IRQ);
	
	milisec++;
	
	enable_irq(KBD_IRQ);
}




void beep() 
{
	//timer 0 programming
	timer_init(0, LCOM_MODE);
	timer_load(0, (int) (TIMER_CLK/1000) );
	
	//install Timer 0 handler
	_go32_dpmi_seginfo original_vec_c; //old ints status
	install_c_irq_handler(T0_IRQ, timer_0_handler, &original_vec_c); 
	
	
	//timer 2 programming
	
	//frequency definition
	int frequency = 1318.51;
	int divisor = TIMER_CLK / frequency;
	
	timer_init(2,LCOM_MODE); //programs timer 2
	timer_load(2, (int)divisor ); //loads frequency
	
	//Speaker on
	outportb(SPEAKER_CTRL, TIMER2_ENABLE | SPEAKER_ENABLE);
	
	//waits 1 sec
	mili_sleep(1000);
	
	//Speaker off
	outportb(SPEAKER_CTRL, SPEAKER_DISABLE);
	
	//reinstall original handler
	reinstall_c_irq_handler(T0_IRQ, &original_vec_c);
}

